package com.ocom.payhandle.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ocom.common.entity.card.EntityXfRecord;
import com.ocom.common.entity.card.EntityXfRecordProcess;
import com.ocom.common.entity.card.EntityXfRecordProcessExxx;
import com.ocom.common.entity.card.EntityXfUserParamConfig;
import com.ocom.common.enums.DataSourceEnum;
import com.ocom.common.resp.Result;
import com.ocom.common.vo.pyhandle.ConsTimeZoneVo;
import com.ocom.mysql.aspect.DataSourceAspect;
import com.ocom.payhandle.dao.IDaoXfUserparamConfig;
import com.ocom.payhandle.feign.XfRecordFeign;
import com.ocom.payhandle.fun.ShoppingCartPayLimitService;
import com.ocom.payhandle.service.XfRecordProcessService;
import com.ocom.payhandle.service.XfRepairpayConfigService;
import com.ocom.payhandle.service.XfUserparamConfigService;
import com.ocom.payhandle.service.XfZoneDateService;
import com.ocom.redis.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class XfUserparamConfigServiceImpl extends ServiceImpl<IDaoXfUserparamConfig, EntityXfUserParamConfig> implements XfUserparamConfigService {

    @Autowired
    private IDaoXfUserparamConfig iDaoXfUserparamConfig;

    @Autowired
    private XfRecordProcessService xfRecordProcessService;

    @Autowired
    XfZoneDateService xfZoneDateService;

    @Autowired
    XfRepairpayConfigService xfRepairpayConfigService;

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private XfRecordFeign xfRecordFeign;

    @Autowired
    private ShoppingCartPayLimitService shoppingCartPayLimitService;

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "companyId")
    @Override
    public Integer selectLimit(Long companyId, Long pId, Integer accountType, Integer consType, Date consDate, Integer consMeal, Integer realAmount,boolean bj) {

        //计算时区
        Integer timeZone = 0;

        try {
            ConsTimeZoneVo consTimeZoneVo = xfZoneDateService.getTimeZone(companyId, consDate);
            timeZone = consTimeZoneVo.getConsTimeZone();
        } catch (Exception e1) {
            log.error("查时区异常【{}】【{}】【{}】", companyId, consDate, e1);
        }

        try {
            String canKey = "";
            Long timeLong = Long.valueOf(4 * 60 * 60);
            EntityXfUserParamConfig entityXfUserParamConfig = null;
            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + consMeal + "#timeZone:0#";
            Object object = redisUtil.get(canKey);
            //饭堂才有餐段限制  商店只处理按月按天  TODO
            if (consType == 1) {
                if (object == null) {
                    QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("com_id", companyId);
                    queryWrapper.eq("cons_type", consType);
                    queryWrapper.eq("meal_no", consMeal);
                    queryWrapper.eq("acc_type_id", accountType);
                    queryWrapper.eq("cons_time_zone", timeZone);
                    queryWrapper.eq("limit_field", 0);
                    queryWrapper.select("times_limit", "amount_limit");
                    queryWrapper.orderByDesc("update_time");
                    queryWrapper.last("limit 1");
                    entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                    if(entityXfUserParamConfig==null){
                        redisUtil.set(canKey, "null", timeLong);
                    }else{
                        redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                    }
                } else {
                    if(object.toString().equals("null")){
                        entityXfUserParamConfig= null;
                    }else{
                        entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                    }
                }

//                if (entityXfUserParamConfig == null) {
//                    return 0;
//                }
//                if (entityXfUserParamConfig.getTimesLimit() == -1 && entityXfUserParamConfig.getAmountLimit() == -1) {
//                    return 0;
//                }
                if (entityXfUserParamConfig != null && entityXfUserParamConfig.getTimesLimit() == 0) {
                    return 1;
                }

            }

            //判断redis,把查询出来的限制参数保存入redis
            EntityXfRecord entityXfRecord = new EntityXfRecord();
            entityXfRecord.setPId(Long.valueOf(pId));
            entityXfRecord.setConsType(consType);
            entityXfRecord.setMealNo(String.valueOf(consMeal));
            entityXfRecord.setComId(companyId);
            entityXfRecord.setConsTime(consDate);

            if (consType == 1 && entityXfUserParamConfig != null) {
                Result result = null;
                if(bj){
                    result = xfRecordProcessService.getWaitPayLimit(companyId,entityXfRecord);
                }else{
                    result = xfRecordProcessService.xfUserparam(companyId,entityXfRecord);
//                    result = xfRecordFeign.xfUserparam(entityXfRecord);
                }
                int intRet = limit(result, entityXfUserParamConfig, realAmount);
                if (intRet != 0) {
                    return intRet;
                }
            }


            //还有继续查询天和月
            entityXfRecord.setMealNo(String.valueOf(500));

            Result resultWu = null;
            if(bj){
                resultWu = xfRecordProcessService.getWaitPayLimit(companyId,entityXfRecord);
            }else{
                resultWu = xfRecordProcessService.xfUserparam(companyId,entityXfRecord);
//                resultWu = xfRecordFeign.xfUserparam(entityXfRecord);
            }
            if (resultWu.getCode() != 200) {
                return 7;
            }

            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + entityXfRecord.getMealNo() + "#timeZone:" + timeZone + "#";
            object = redisUtil.get(canKey);
            if (object == null) {
                QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("com_id", companyId);
                queryWrapper.eq("cons_type", consType);
                queryWrapper.eq("meal_no", entityXfRecord.getMealNo());
                queryWrapper.eq("acc_type_id", accountType);
                queryWrapper.eq("cons_time_zone", timeZone);
                queryWrapper.eq("limit_field", 0);
                queryWrapper.select("times_limit", "amount_limit");
                queryWrapper.orderByDesc("update_time");
                queryWrapper.last("limit 1");
                entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                if(entityXfUserParamConfig==null){
                    redisUtil.set(canKey, "null", timeLong);
                }else{
                    redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                }
            } else {
                if(object.toString().equals("null")){
                    entityXfUserParamConfig= null;
                }else{
                    entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                }
            }

            int intRet = limit(resultWu, entityXfUserParamConfig, realAmount);
            if (intRet != 0) {
                return intRet + 2;
            }

            entityXfRecord.setMealNo(String.valueOf(1000));

            Result resultQian = null;
            if(bj){
                resultQian = xfRecordProcessService.getWaitPayLimit(companyId,entityXfRecord);
            }else{
//                resultQian = xfRecordFeign.xfUserparam(entityXfRecord);
                resultQian = xfRecordProcessService.xfUserparam(companyId,entityXfRecord);
            }
            if (resultQian.getCode() != 200) {
                return 7;
            }
            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + entityXfRecord.getMealNo() + "#timeZone:" + timeZone + "#";
            object = redisUtil.get(canKey);
            if (object == null) {
                QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("com_id", companyId);
                queryWrapper.eq("cons_type", consType);
                queryWrapper.eq("meal_no", entityXfRecord.getMealNo());
                queryWrapper.eq("acc_type_id", accountType);
                queryWrapper.eq("cons_time_zone", timeZone);
                queryWrapper.select("times_limit", "amount_limit");
                queryWrapper.eq("limit_field", 0);
                queryWrapper.orderByDesc("update_time");
                queryWrapper.last("limit 1");
                entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                if(entityXfUserParamConfig==null){
                    redisUtil.set(canKey, "null", timeLong);
                }else{
                    redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                }
            } else {
                if(object.toString().equals("null")){
                    entityXfUserParamConfig= null;
                }else{
                    entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                }
            }
            int intQianRet = limit(resultQian, entityXfUserParamConfig, realAmount);
            if (intQianRet != 0) {
                return intQianRet + 4;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    private int limit(Result result, EntityXfUserParamConfig entityXfUserParamConfig, Integer realAmount) {
        if (result == null || result.getData() == null) {
            return 0;
        }
        int amount = 0;
        if (result.getCode() != 200) {
            return 7;
        }
        if (entityXfUserParamConfig == null) {
            return 0;
        }
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result.getData()));
        if (entityXfUserParamConfig.getTimesLimit() != -1) {
            if (entityXfUserParamConfig.getTimesLimit() <= jsonObject.getInteger("times")) {
                return 1;
            }
        }
        if (entityXfUserParamConfig.getAmountLimit() != -1) {
            amount = entityXfUserParamConfig.getAmountLimit() + jsonObject.getInteger("amount");
            if (amount < realAmount) {
                return 2;
            }
        }
        return 0;
    }


    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "companyId")
    public Integer getRestrict(Long companyId, Long pId, Integer accountType, Integer consType, Date consDate, Integer consMeal, Integer discount, EntityXfRecordProcess entityXfRecordProcess, List<EntityXfRecordProcessExxx> processExxxList) {
        try {
            //计算时区
            Integer timeZone = 0;

            try {
                ConsTimeZoneVo consTimeZoneVo = xfZoneDateService.getTimeZone(companyId, consDate);
                timeZone = consTimeZoneVo.getConsTimeZone();
            } catch (Exception e1) {
                log.error("查时区异常【{}】【{}】【{}】", companyId, consDate, e1);
            }

            String canKey = "";
            Long timeLong = Long.valueOf(4 * 60 * 60);
            EntityXfUserParamConfig entityXfUserParamConfig = null;

            //判断redis,把查询出来的限制参数保存入redis
            EntityXfRecord entityXfRecord = new EntityXfRecord();
            entityXfRecord.setPId(Long.valueOf(pId));
            entityXfRecord.setConsType(consType);
            entityXfRecord.setMealNo(String.valueOf(consMeal));
            entityXfRecord.setComId(companyId);
            entityXfRecord.setConsTime(consDate);
            Object object = null;
            Result resultWu = null;

            //按月
            entityXfRecord.setMealNo(String.valueOf(1000));
            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + entityXfRecord.getMealNo() + "#timeZone:" + timeZone + "#limitField:5";
            object = redisUtil.get(canKey);
            if (object == null) {
                QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("com_id", companyId);
                queryWrapper.eq("cons_type", consType);
                queryWrapper.eq("meal_no", entityXfRecord.getMealNo());
                queryWrapper.eq("acc_type_id", accountType);
                queryWrapper.eq("cons_time_zone", timeZone);
                queryWrapper.eq("limit_field", 5);
                queryWrapper.select("times_limit", "amount_limit");
                queryWrapper.orderByDesc("update_time");
                queryWrapper.last("limit 1");
                entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                if(entityXfUserParamConfig==null){
                    redisUtil.set(canKey, "null", timeLong);
                }else{
                    redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                }
            } else {
                if(object.toString().equals("null")){
                    entityXfUserParamConfig= null;
                }else{
                    entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                }
            }
            if (entityXfUserParamConfig != null) {
                if(processExxxList!=null){
                    resultWu = shoppingCartPayLimitService.xfUserparamDiscount(entityXfRecord,processExxxList);
                }else{
//                    resultWu = xfRecordFeign.xfUserparamDiscount(entityXfRecord);
                    resultWu = xfRecordProcessService.xfUserparamDiscount(companyId,entityXfRecord);
                }
                if (resultWu.getCode() != 200) {
                    return discount;
                }

                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(resultWu.getData()));
                if (entityXfUserParamConfig.getTimesLimit() != -1) {
                    if (entityXfUserParamConfig.getTimesLimit() <= jsonObject.getInteger("times")) {
                        return 0;
                    }
                }
                if (entityXfUserParamConfig.getAmountLimit() != -1) {
                    if (entityXfUserParamConfig.getAmountLimit() <= jsonObject.getInteger("amount")) {
                        return 0;
                    }
                    discount = entityXfUserParamConfig.getAmountLimit() - jsonObject.getInteger("amount");
                    if (discount <= 0) {
                        return 0;
                    }
                }
            }


            //  按月/餐限制优惠
            Integer monthMealKey = consMeal + 900;
            entityXfRecord.setMealNo(String.valueOf(monthMealKey));
            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + entityXfRecord.getMealNo() + "#timeZone:" + timeZone + "#limitField:5";
            object = redisUtil.get(canKey);
            if (object == null) {
                QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("com_id", companyId);
                queryWrapper.eq("cons_type", consType);
                queryWrapper.eq("meal_no", entityXfRecord.getMealNo());
                queryWrapper.eq("acc_type_id", accountType);
                queryWrapper.eq("cons_time_zone", timeZone);
                queryWrapper.eq("limit_field", 5);
                queryWrapper.select("times_limit", "amount_limit");
                queryWrapper.orderByDesc("update_time");
                queryWrapper.last("limit 1");
                entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                if(entityXfUserParamConfig==null){
                    redisUtil.set(canKey, "null", timeLong);
                }else{
                    redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                }
            } else {
                if(object.toString().equals("null")){
                    entityXfUserParamConfig= null;
                }else{
                    entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                }
            }
            if (entityXfUserParamConfig != null) {
                if(processExxxList!=null){
                    resultWu = shoppingCartPayLimitService.xfUserparamDiscount(entityXfRecord,processExxxList);
                }else{
//                    resultWu = xfRecordFeign.xfUserparamDiscount(entityXfRecord);
                    resultWu = xfRecordProcessService.xfUserparamDiscount(companyId,entityXfRecord);
                }
                if (resultWu.getCode() != 200) {
                    return discount;
                }

                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(resultWu.getData()));
                if (entityXfUserParamConfig.getTimesLimit() != -1) {
                    if (entityXfUserParamConfig.getTimesLimit() <= jsonObject.getInteger("times")) {
                        return 0;
                    }
                }
                if (entityXfUserParamConfig.getAmountLimit() != -1) {
                    if (entityXfUserParamConfig.getAmountLimit() <= jsonObject.getInteger("amount")) {
                        return 0;
                    }
                    discount = entityXfUserParamConfig.getAmountLimit() - jsonObject.getInteger("amount");
                    if (discount <= 0) {
                        return 0;
                    }
                }
            }





            ////按天
            entityXfRecord.setMealNo(String.valueOf(500));
            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + entityXfRecord.getMealNo() + "#timeZone:" + timeZone + "#limitField:5";
            object = redisUtil.get(canKey);
            if (object == null) {
                QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("com_id", companyId);
                queryWrapper.eq("cons_type", consType);
                queryWrapper.eq("meal_no", entityXfRecord.getMealNo());
                queryWrapper.eq("acc_type_id", accountType);
                queryWrapper.eq("cons_time_zone", timeZone);
                queryWrapper.eq("limit_field", 5);
                queryWrapper.select("times_limit", "amount_limit");
                queryWrapper.orderByDesc("update_time");
                queryWrapper.last("limit 1");
                entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                if(entityXfUserParamConfig==null){
                    redisUtil.set(canKey, "null", timeLong);
                }else{
                    redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                }
            } else {
                if(object.toString().equals("null")){
                    entityXfUserParamConfig= null;
                }else{
                    entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                }
            }

            if (entityXfUserParamConfig != null) {
                if(processExxxList!=null){
                    resultWu = shoppingCartPayLimitService.xfUserparamDiscount(entityXfRecord,processExxxList);
                }else{
//                    resultWu = xfRecordFeign.xfUserparamDiscount(entityXfRecord);
                    resultWu = xfRecordProcessService.xfUserparamDiscount(companyId,entityXfRecord);
                }
                if (resultWu.getCode() != 200) {
                    return discount;
                }
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(resultWu.getData()));
                if (entityXfUserParamConfig.getTimesLimit() != -1) {
                    if (entityXfUserParamConfig.getTimesLimit() <= jsonObject.getInteger("times")) {
                        return 0;
                    }
                }
                if (entityXfUserParamConfig.getAmountLimit() != -1) {
                    if (entityXfUserParamConfig.getAmountLimit() <= jsonObject.getInteger("amount")) {
                        return 0;
                    }
                    Integer discount2 = entityXfUserParamConfig.getAmountLimit() - jsonObject.getInteger("amount");
                    if (discount2 <= 0) {
                        return 0;
                    }
                    //限制取更小的值
                    if(discount2<discount){
                        discount = discount2;
                    }
                }
            }

            //按餐
            entityXfRecord.setMealNo(consMeal.toString());
            canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType + "#consType:" + consType + "#mealNo:" + consMeal + "#timeZone:" + timeZone + "#limitField:5";
            object = redisUtil.get(canKey);
            //饭堂才有餐段限制  商店只处理按月按天  TODO
            if (consType == 1) {
                if (object == null) {
                    QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("com_id", companyId);
                    queryWrapper.eq("cons_type", consType);
                    queryWrapper.eq("meal_no", consMeal);
                    queryWrapper.eq("acc_type_id", accountType);
                    queryWrapper.eq("cons_time_zone", timeZone);
                    queryWrapper.eq("limit_field", 5);
                    queryWrapper.select("times_limit", "amount_limit");
                    queryWrapper.orderByDesc("update_time");
                    queryWrapper.last("limit 1");
                    entityXfUserParamConfig = iDaoXfUserparamConfig.selectOne(queryWrapper);
                    if(entityXfUserParamConfig==null){
                        redisUtil.set(canKey, "null", timeLong);
                    }else{
                        redisUtil.set(canKey, entityXfUserParamConfig, timeLong);
                    }
                } else {
                    if(object.toString().equals("null")){
                        entityXfUserParamConfig= null;
                    }else{
                        entityXfUserParamConfig = JSON.parseObject(JSON.toJSONString(object), EntityXfUserParamConfig.class);
                    }
                }

                if (entityXfUserParamConfig != null) {
                    if (entityXfUserParamConfig.getTimesLimit() == 0 || entityXfUserParamConfig.getAmountLimit() == 0) {
                        return discount;
                    } else if (entityXfUserParamConfig.getTimesLimit() == -1 && entityXfUserParamConfig.getAmountLimit() == -1) {
                        return discount;
                    }
                }
            }

            if (consType == 1 && entityXfUserParamConfig != null) {
                if(processExxxList!=null){
                    resultWu = shoppingCartPayLimitService.xfUserparamDiscount(entityXfRecord,processExxxList);
                }else{
//                    resultWu = xfRecordFeign.xfUserparamDiscount(entityXfRecord);
                    resultWu = xfRecordProcessService.xfUserparamDiscount(companyId,entityXfRecord);
                }
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(resultWu.getData()));
                if (entityXfUserParamConfig.getTimesLimit() != -1) {
                    if (entityXfUserParamConfig.getTimesLimit() <= jsonObject.getInteger("times")) {
                        return 0;
                    }
                }
                if (entityXfUserParamConfig.getAmountLimit() != -1) {
                    if (entityXfUserParamConfig.getAmountLimit() <= jsonObject.getInteger("amount")) {
                        return 0;
                    }
                    Integer discount2 = entityXfUserParamConfig.getAmountLimit() - jsonObject.getInteger("amount");
                    if (discount2 <= 0) {
                        return 0;
                    }
                    //限制取更小的值
                    if(discount2<discount){
                        discount = discount2;
                    }
                }
            }
            return discount;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "companyId")
    public Integer ifLimit(Long companyId, Integer accountType, Integer priority) {
        if(accountType==null || accountType == 0) return priority;

        String canKey = "xf_userparam_config#comId:" + companyId + "#accTypeId:" + accountType ;

        Long timeLong = Long.valueOf(4 * 60 * 60);
        Object object = redisUtil.get(canKey);
        //饭堂才有餐段限制  商店只处理按月按天  TODO

        Integer count = 0 ;

        if (object == null) {
            QueryWrapper<EntityXfUserParamConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("com_id", companyId);
            queryWrapper.eq("acc_type_id", accountType);
            queryWrapper.apply(" (times_limit != -1 or amount_limit != -1 ) ");
            count = this.count(queryWrapper);
            redisUtil.set(canKey, count, timeLong);
        }else{
            count = (Integer) object;
        }
        if(count>0){
            return 10;
        }else{
            return priority;
        }

    }

}
